package euler.p001_050;

import euler.MainEuler;
import euler.helper.NaturalHelper;

public class Euler017 extends MainEuler {

    /*
        If the numbers 1 to 5 are written out in words:
        one, two, three, four, five,
        then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

        If all the numbers from 1 to 1000
        (one thousand) inclusive were written out in words, how many letters would be used?

        NOTE: Do not count spaces or hyphens.
        For example, 342 (three hundred and forty-two) contains 23 letters
        and 115 (one hundred and fifteen) contains 20 letters.

        The use of "and" when writing out numbers is in compliance with British usage.

     */
    public String resolve(int limite) {
        int suma = 0;

        for (int i = 1; i<=limite; i++) {
            String letras = letras(i);;
            suma+=letras.length();
        }

        return String.valueOf(suma);
    }

    private String letras(int i) {
        StringBuilder sb = new StringBuilder();
        calcularMiles(sb,NaturalHelper.digito(i, 3, 10));

        int centenas = NaturalHelper.digito(i, 2, 10);;
        calcularCentenas(sb,centenas);

        int decenas = NaturalHelper.digito(i, 1, 10);
        int unidades = NaturalHelper.digito(i, 0, 10);

        if (centenas != 0 && (decenas != 0 || unidades != 0)) {
            sb.append("and");
        }

        calcularDecenasUnidades(sb,decenas,unidades);

        return sb.toString();
    }

    private void calcularDecenasUnidades(StringBuilder sb, int decenas, int unidades) {

        switch (decenas) {
            case 0: break;
            case 1:
                switch (unidades) {
                    case 0: sb.append("ten"); break;
                    case 1: sb.append("eleven"); break;
                    case 2: sb.append("twelve"); break;
                    case 3: sb.append("thirteen"); break;
                    case 4: sb.append("fourteen"); break;
                    case 5: sb.append("fifteen"); break;
                    case 6: sb.append("sixteen"); break;
                    case 7: sb.append("seventeen"); break;
                    case 8: sb.append("eighteen"); break;
                    case 9: sb.append("nineteen"); break;

                    default: throw new IllegalArgumentException("Digito invalido " + unidades);
                }
                break;
            case 2: sb.append("twenty"); break;
            case 3: sb.append("thirty"); break;
            case 4: sb.append("forty"); break;
            case 5: sb.append("fifty"); break;
            case 6: sb.append("sixty"); break;
            case 7: sb.append("seventy"); break;
            case 8: sb.append("eighty"); break;
            case 9: sb.append("ninety"); break;
        }

        if (decenas != 1) {
            switch (unidades) {
                case 0: break;
                case 1: sb.append("one"); break;
                case 2: sb.append("two"); break;
                case 3: sb.append("three"); break;
                case 4: sb.append("four"); break;
                case 5: sb.append("five"); break;
                case 6: sb.append("six"); break;
                case 7: sb.append("seven"); break;
                case 8: sb.append("eight"); break;
                case 9: sb.append("nine"); break;

                default: throw new IllegalArgumentException("Digito invalido " + unidades);
            }
        }
    }

    private void calcularMiles(StringBuilder sb, int digito) {
        if (digito == 1) {
            sb.append("one").append("thousand");
        }
    }

    private void calcularCentenas(StringBuilder sb, int digito) {

        switch (digito) {
            case 1: sb.append("one"); break;
            case 2: sb.append("two"); break;
            case 3: sb.append("three"); break;
            case 4: sb.append("four"); break;
            case 5: sb.append("five"); break;
            case 6: sb.append("six"); break;
            case 7: sb.append("seven"); break;
            case 8: sb.append("eight"); break;
            case 9: sb.append("nine"); break;
            case 0: break;

            default: throw new IllegalArgumentException("Digito invalido " + digito);
        }

        if (digito != 0) {
            sb.append("hundred");
        }
    }
}
